using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using UnityEngine;
using Ping = System.Net.NetworkInformation.Ping;

namespace Gj.Network
{
    /// <summary>
    /// 局域网网络状态检测器
    /// 提供局域网网络质量评估和状态监控功能
    /// </summary>
    public class LocalNetworkStatus
    {
        private static LocalNetworkStatus _instance;
        public static LocalNetworkStatus Instance => _instance ??= new LocalNetworkStatus();

        /// <summary>
        /// 网络状态枚举
        /// </summary>
        public enum NetworkQuality
        {
            Excellent,  // 优秀 - 延迟 < 10ms, 丢包率 < 1%
            Good,       // 良好 - 延迟 < 30ms, 丢包率 < 3%
            Fair,       // 一般 - 延迟 < 100ms, 丢包率 < 5%
            Poor,       // 较差 - 延迟 < 300ms, 丢包率 < 10%
            Bad         // 很差 - 延迟 >= 300ms 或 丢包率 >= 10%
        }

        /// <summary>
        /// 网络状态信息
        /// </summary>
        [System.Serializable]
        public class NetworkStatusInfo
        {
            public NetworkQuality quality;
            public float averageLatency;      // 平均延迟(ms)
            public float packetLossRate;     // 丢包率(%)
            public bool isConnected;         // 是否连接
            public DateTime lastChecked;      // 最后检查时间
            public int testCount;            // 测试次数
            public int successCount;         // 成功次数
            public int failureCount;         // 失败次数

            public NetworkStatusInfo()
            {
                quality = NetworkQuality.Bad;
                averageLatency = float.MaxValue;
                packetLossRate = 100f;
                isConnected = false;
                lastChecked = DateTime.MinValue;
                testCount = 0;
                successCount = 0;
                failureCount = 0;
            }
        }

        private NetworkStatusInfo _currentStatus = new NetworkStatusInfo();
        private readonly object _lockObject = new object();
        private bool _isTesting = false;
        private readonly List<string> _testTargets = new List<string>
        {
            "8.8.8.8",      // Google DNS
            "114.114.114.114", // 国内DNS
            "223.5.5.5"     // 阿里DNS
        };

        /// <summary>
        /// 获取当前网络状态
        /// </summary>
        public NetworkStatusInfo GetCurrentStatus()
        {
            lock (_lockObject)
            {
                return new NetworkStatusInfo
                {
                    quality = _currentStatus.quality,
                    averageLatency = _currentStatus.averageLatency,
                    packetLossRate = _currentStatus.packetLossRate,
                    isConnected = _currentStatus.isConnected,
                    lastChecked = _currentStatus.lastChecked,
                    testCount = _currentStatus.testCount,
                    successCount = _currentStatus.successCount,
                    failureCount = _currentStatus.failureCount
                };
            }
        }

        /// <summary>
        /// 检查网络状态（异步）
        /// </summary>
        /// <param name="testCount">测试次数，默认10次</param>
        /// <param name="timeout">超时时间(ms)，默认3000ms</param>
        /// <returns>网络状态信息</returns>
        public async Task<NetworkStatusInfo> CheckNetworkStatusAsync(int testCount = 10, int timeout = 3000)
        {
            if (_isTesting)
            {
                Debug.LogWarning("[LocalNetworkStatus] Network test is already running, returning current status");
                return GetCurrentStatus();
            }

            _isTesting = true;
            try
            {
                var status = new NetworkStatusInfo();
                var latencies = new List<float>();
                var successCount = 0;
                var totalTests = 0;

                // 对每个测试目标进行ping测试
                foreach (var target in _testTargets)
                {
                    for (int i = 0; i < testCount / _testTargets.Count; i++)
                    {
                        try
                        {
                            using (var ping = new Ping())
                            {
                                var reply = await Task.Run(() => ping.Send(target, timeout));
                                totalTests++;

                                if (reply.Status == IPStatus.Success)
                                {
                                    latencies.Add(reply.RoundtripTime);
                                    successCount++;
                                }
                                else
                                {
                                    Debug.LogWarning($"[LocalNetworkStatus] Ping to {target} failed: {reply.Status}");
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.LogError($"[LocalNetworkStatus] Error pinging {target}: {ex.Message}");
                            totalTests++;
                        }

                        // 避免过于频繁的测试
                        await Task.Delay(100);
                    }
                }

                // 计算统计信息
                if (latencies.Count > 0)
                {
                    status.averageLatency = CalculateAverage(latencies);
                    status.packetLossRate = ((float)(totalTests - successCount) / totalTests) * 100f;
                    status.isConnected = true;
                    status.successCount = successCount;
                    status.failureCount = totalTests - successCount;
                    status.testCount = totalTests;
                    status.quality = EvaluateNetworkQuality(status.averageLatency, status.packetLossRate);
                }
                else
                {
                    status.isConnected = false;
                    status.packetLossRate = 100f;
                    status.quality = NetworkQuality.Bad;
                    status.failureCount = totalTests;
                    status.testCount = totalTests;
                }

                status.lastChecked = DateTime.Now;

                // 更新当前状态
                lock (_lockObject)
                {
                    _currentStatus = status;
                }

                Debug.Log($"[LocalNetworkStatus] Network check completed - Quality: {status.quality}, " +
                         $"Latency: {status.averageLatency:F1}ms, Loss: {status.packetLossRate:F1}%");

                return status;
            }
            finally
            {
                _isTesting = false;
            }
        }

        /// <summary>
        /// 快速检查网络连接状态
        /// </summary>
        /// <returns>是否连接</returns>
        public async Task<bool> IsConnectedAsync()
        {
            try
            {
                using (var ping = new Ping())
                {
                    var reply = await Task.Run(() => ping.Send("8.8.8.8", 2000));
                    return reply.Status == IPStatus.Success;
                }
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 获取网络质量建议
        /// </summary>
        /// <param name="quality">网络质量</param>
        /// <returns>建议信息</returns>
        public string GetQualitySuggestion(NetworkQuality quality)
        {
            return quality switch
            {
                NetworkQuality.Excellent => "网络状况优秀，适合所有网络应用",
                NetworkQuality.Good => "网络状况良好，适合大部分网络应用",
                NetworkQuality.Fair => "网络状况一般，建议优化网络环境",
                NetworkQuality.Poor => "网络状况较差，建议检查网络连接",
                NetworkQuality.Bad => "网络状况很差，请检查网络连接或联系网络管理员",
                _ => "未知网络状况"
            };
        }

        /// <summary>
        /// 计算平均延迟
        /// </summary>
        private float CalculateAverage(List<float> values)
        {
            if (values.Count == 0) return 0f;

            float sum = 0f;
            foreach (var value in values)
            {
                sum += value;
            }
            return sum / values.Count;
        }

        /// <summary>
        /// 评估网络质量
        /// </summary>
        private NetworkQuality EvaluateNetworkQuality(float latency, float packetLoss)
        {
            if (packetLoss >= 10f || latency >= 300f)
                return NetworkQuality.Bad;
            else if (packetLoss >= 5f || latency >= 100f)
                return NetworkQuality.Poor;
            else if (packetLoss >= 3f || latency >= 30f)
                return NetworkQuality.Fair;
            else if (packetLoss >= 1f || latency >= 10f)
                return NetworkQuality.Good;
            else
                return NetworkQuality.Excellent;
        }

        /// <summary>
        /// 重置状态
        /// </summary>
        public void Reset()
        {
            lock (_lockObject)
            {
                _currentStatus = new NetworkStatusInfo();
            }
        }
    }
}
